package com.example.helloandroid;

import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

public class HelloAndroid extends Activity {

	private static final String TAG = "HelloAndroid";

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.i(TAG, "onCreate()");

		Debug.startMethodTracing("HelloAndroid");

		setContentView(R.layout.main);

		// startService(new Intent(HelloAndroid.this, LocalService.class));

		// bindService(new Intent(HelloAndroid.this, LocalService.class),
		// mLocalConnection, Context.BIND_AUTO_CREATE);

		// startService(new
		// Intent("com.example.helloandroid.HelloAndroid.REMOTE_SERVICE"));

		//bindService(new Intent(IRemoteService.class.getName()),
		//		mRemoteConnection, Context.BIND_AUTO_CREATE);
		
		//startService(new Intent(HelloAndroid.this, MessengerService.class));
		
		bindService(new Intent(IMessengerService.class.getName()),
				mMessengerConnection, Context.BIND_AUTO_CREATE);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		Log.i(TAG, "onDestory()");

		// stopService(new Intent(HelloAndroid.this, LocalService.class));

		// unbindService(mLocalConnection);

		// stopService(new Intent("com.example.helloandroid.REMOTE_SERVICE"));

		//unbindService(mRemoteConnection);

		//stopService(new Intent(HelloAndroid.this, MessengerService.class));
		
		unbindService(mMessengerConnection);

		Debug.stopMethodTracing();
	}

	private ServiceConnection mLocalConnection = new ServiceConnection() {
		private static final String TAG = "LocalConnection";

		public void onServiceConnected(ComponentName className, IBinder service) {
			LocalService localService = ((LocalService.LocalBinder) service)
					.getService();
			localService.showNotification("onServiceConnected()");
			Log.i(TAG, "onServiceConnected()");
		}

		public void onServiceDisconnected(ComponentName className) {
			Log.i(TAG, "onServiceDisconnected()");
		}
	};

	private ServiceConnection mRemoteConnection = new ServiceConnection() {
		private static final String TAG = "RemoteConnection";

		public void onServiceConnected(ComponentName className, IBinder service) {
			Log.i(TAG, "onServiceConnected()");
			IRemoteService remoteService = IRemoteService.Stub
					.asInterface(service);
			try {
				remoteService.showNotification("onServiceConnected()");
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}

		public void onServiceDisconnected(ComponentName className) {
			Log.i(TAG, "onServiceDisconnected()");
		}
	};

	private ServiceConnection mMessengerConnection = new ServiceConnection() {
		private static final String TAG = "MessengerConnection";

		public void onServiceConnected(ComponentName className, IBinder service) {
			Log.i(TAG, "onServiceConnected()");
			Messenger messengerService = new Messenger(service);
			try {
				Bundle b = new Bundle();
				b.putString("msg", "onServiceConnected");
				messengerService.send(Message.obtain(null, IMessengerService.MSG_SHOW_NOTIFICATION, b));
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}

		public void onServiceDisconnected(ComponentName className) {
			Log.i(TAG, "onServiceDisconnected()");
		}
	};

	public static class RemoteService extends Service {

		private static final String TAG = "RemoteService";

		private RemoteBinder mRemoteBinder = null;

		@Override
		public void onCreate() {
			Log.i(TAG, "onCreate()");
			super.onCreate();

			mRemoteBinder = new RemoteBinder();
		}

		@Override
		public void onDestroy() {
			Log.i(TAG, "onDestory()");
			super.onDestroy();
		}

		@Override
		public int onStartCommand(Intent intent, int flags, int startId) {
			Log.i(TAG, "onStartCommand()");
			try {
				mRemoteBinder.showNotification("onStartCommand");
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			return super.onStartCommand(intent, flags, startId);
		}

		@Override
		public boolean onUnbind(Intent intent) {
			Log.i(TAG, "onUnbind()");
			return super.onUnbind(intent);
		}

		@Override
		public IBinder onBind(Intent intent) {
			Log.i(TAG, "onBind()");
			try {
				mRemoteBinder.showNotification("onBind");
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			return mRemoteBinder;
		}

		private class RemoteBinder extends IRemoteService.Stub {
			private static final String TAG = "RemoteBinder";
			private Toast toast = makeNotification(getApplicationContext());

			private Toast makeNotification(Context context) {
				int duration = Toast.LENGTH_LONG;

				return Toast.makeText(context, null, duration);
			}

			public void showNotification(String msg) throws RemoteException {
				Log.i(TAG, "showNotification(" + msg + ")");

				toast.setText(msg);
				toast.show();
			}
		}
	}

	public static class LocalService extends Service {

		private static final String TAG = "LocalService";

		@Override
		public void onCreate() {
			Log.i(TAG, "onCreate()");
			super.onCreate();
		}

		@Override
		public void onDestroy() {
			Log.i(TAG, "onDestory()");
			super.onDestroy();
		}

		@Override
		public int onStartCommand(Intent intent, int flags, int startId) {
			Log.i(TAG, "onStartCommand()");
			showNotification("onStartCommand");
			return super.onStartCommand(intent, flags, startId);
		}

		@Override
		public boolean onUnbind(Intent intent) {
			Log.i(TAG, "onUnbind()");
			return super.onUnbind(intent);
		}

		@Override
		public IBinder onBind(Intent intent) {
			Log.i(TAG, "onBind()");
			return new LocalBinder();
		}

		private class LocalBinder extends Binder {
			LocalService getService() {
				Log.i(TAG, "getService()");
				return LocalService.this;
			}
		}

		private void showNotification(String msg) {
			Context context = getApplicationContext();
			CharSequence text = msg;
			int duration = Toast.LENGTH_LONG;

			Toast toast = Toast.makeText(context, text, duration);
			toast.show();
		}

	}

	public static class MessengerService extends Service implements
			IMessengerService {

		private static final String TAG = "MessengerService";

		private Messenger mMessenger = null;

		@Override
		public void onCreate() {
			Log.i(TAG, "onCreate()");
			super.onCreate();

			mMessenger = new Messenger(new IncommingHandler());
		}

		@Override
		public void onDestroy() {
			Log.i(TAG, "onDestory()");
			super.onDestroy();
		}

		@Override
		public int onStartCommand(Intent intent, int flags, int startId) {
			Log.i(TAG, "onStartCommand()");
			try {
				Bundle b = new Bundle();
				b.putString("msg", "onStartCommand");
				mMessenger.send(Message.obtain(null, IMessengerService.MSG_SHOW_NOTIFICATION, b));
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			return super.onStartCommand(intent, flags, startId);
		}

		@Override
		public boolean onUnbind(Intent intent) {
			Log.i(TAG, "onUnbind()");
			return super.onUnbind(intent);
		}

		@Override
		public IBinder onBind(Intent intent) {
			Log.i(TAG, "onBind()");
			try {
				Bundle b = new Bundle();
				b.putString("msg", "OnBind");
				mMessenger.send(Message.obtain(null, IMessengerService.MSG_SHOW_NOTIFICATION, b));
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			return mMessenger.getBinder();
		}

		private class IncommingHandler extends Handler {
			@Override
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case IMessengerService.MSG_SHOW_NOTIFICATION:
					Bundle b = (Bundle)msg.obj;
					showNotification(b.getString("msg"));
					break;
				default:
					super.handleMessage(msg);
				}
				super.handleMessage(msg);
			}

			private static final String TAG = "IncommingBinder";
			private Toast toast = makeNotification(getApplicationContext());

			private Toast makeNotification(Context context) {
				int duration = Toast.LENGTH_LONG;

				return Toast.makeText(context, null, duration);
			}

			public void showNotification(String msg) {
				Log.i(TAG, "showNotification(" + msg + ")");

				toast.setText(msg);
				toast.show();
			}
		}
	}

}
